
/**
 * @file usart1_dma.c
 * @author Model_Hui (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2023-02-16
 * 
 * @copyright Copyright (c) 2023  YouCaiHua Information Technology Co., Ltd
 * 
 */

#include <stdio.h>
#include <string.h>
#include "main.h"
#include "device_id.h"

#include "game_main.h"
#include "uart_data_x.h"

//------------------------------------
// 版本控制
static uart_data_x_t uart_data_x_config;
uint8_t cmd_data_send[USART1_DMA_TX_LEN];

#define CMD_DATA_START_NUM  (8)		//	len before data
#define CMD_BUFF_IS_SEND	(0)
#define CMD_BUFF_IS_REPORT	(1)

// 0xEF 0x37
const uint8_t parms_head[3] = {0xEF, 0x37, 0};
const uint8_t parms_end[2] = {0xFE, 0x73};

#define CMD_CONNECT 			(0x0101)
#define CMD_STATUS 				(0x0102)
#define CMD_COIN_IN 			(0x0103)
#define CMD_GENERAL_CONFIG_GET	(0x0109)
#define CMD_ACCOUNT				(0x010B)
#define CMD_SEND_COIN_PHY		(0x0120)
#define CMD_GAME_OVER			(0x0106)
#define CMD_FAULT				(0x0115)
#define CMD_REGISTER			(0x0801)
#define CMD_LUCKY				(0x0201)
#define CMD_MENU_SET			(0x010F)
#define CMD_MENU_READ			(0x0119)
#define CMD_BOX_INFO			(0x0124)
#define CMD_PAY_CODE			(0x0125)
#define CMD_UPDATE_CHECK	 	(0x0804)
#define CMD_UPDATE_GET_DATA	 	(0x0805)

extern void data_write_reverse(void *destin, void *source, uint16_t len);
extern uint8_t main_data_xor(const uint8_t *data, uint16_t len);

static void uart_data_decode(void);

/**
 * @brief 调用解码初始化,
 * 在业务系统初始化的时候,调用
 */
void uart_data_x_init(void)
{
	memset(&uart_data_x_config, 0, sizeof(uart_data_x_t));
	memset(cmd_data_send, 0, sizeof(cmd_data_send));
}

/**
 * @brief 获取解码buff地址,
 * 
 * @return uint8_t* 
 */
uint8_t *uart_data_x_get_buff_get(void)
{
	return uart_data_x_config.data_get;
}

/**
 * @brief 启动解码,
 * 在获取完串口数据之后，调用
 * @param data_len 
 */
void uart_data_x_startup_decode(uint16_t data_len)
{
	uart_data_x_config.decode_time = UART_DATA_XCODE_TIME_MAX;
	uart_data_x_config.data_get_len = data_len;
	uart_data_x_config.decode_flag = 1;
}

/**
 * @brief 解码计时,
 * 1ms调用一次,建议在业务系统循环中调用
 */
void uart_data_x_timer_1ms(void)
{
	if(uart_data_x_config.decode_flag == 1)
	{
		if(uart_data_x_config.decode_time > 0)
		{
			uart_data_x_config.decode_time--;
		}
		else
		{
			uart_data_x_config.decode_flag = 0;

			uart_data_decode();
		}
	}
}

// ----------------------------------------------------------
// ----------------------------------------------------------
// business data

CMD_connet_callback_t CMD_connet_callback = NULL;
CMD_state_callback_t CMD_state_callback = NULL;
CMD_coin_in_callback_t CMD_coin_in_callback = NULL;
CMD_universal_config_get_callback_t CMD_universal_config_get_callback = NULL;
CMD_account_callback_t CMD_account_callback = NULL;
CMD_coin_phy_callback_t CMD_coin_phy_callback = NULL;
CMD_game_over_callback_t CMD_game_over_callback = NULL;
CMD_fault_callback_t CMD_fault_callback = NULL;
CMD_device_register_callback_t CMD_device_register_callback = NULL;
CMD_lucky_callback_t CMD_lucky_callback = NULL;
CMD_menu_set_callback_t CMD_menu_set_callback = NULL;
CMD_menu_read_callback_t CMD_menu_read_callback = NULL;
CMD_box_info_callback_t CMD_box_info_callback = NULL;
CMD_pay_code_callback_t CMD_pay_code_callback = NULL;
CMD_update_check_callback_t CMD_update_check_callback = NULL;
CMD_update_get_data_callback_t CMD_update_get_data_callback = NULL;

//
//
//
/**
 * @brief 分析指令-勾起回调函数
 * 
 * @param cmd 指令
 * @param param 数据
 */
static void decode_uart_use_data(uint16_t cmd, uint8_t *param)
{
	uint8_t value_u8bit_0 = 0;
	uint8_t value_u8bit_1 = 0;
	uint8_t value_u8bit_2 = 0;
	uint16_t value_u16bit_0 = 0;
	uint16_t value_u16bit_1 = 0;
	uint32_t value_u32bit_0 = 0;
	uint32_t value_u32bit_1 = 0;
	uint8_t buff_44bytes_0[44] = {0};
	uint8_t buff_128bytes_0[128] = {0};

	memset(buff_44bytes_0, 0, sizeof(buff_44bytes_0));
	memset(buff_128bytes_0, 0, sizeof(buff_128bytes_0));

	switch (cmd)
	{
	case CMD_CONNECT:
		{
			CMD_connect_send();

			param += CMD_DATA_START_NUM;
			
			data_write_reverse(&value_u32bit_0, param, 4);
			param += 4;
			
			memcpy(buff_44bytes_0, param, 16);
			
			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;

			if(CMD_connet_callback)
			{
				CMD_connet_callback(value_u32bit_0, buff_44bytes_0, value_u16bit_0);
			}
		}
		break;
	case CMD_STATUS:
		{
			param += CMD_DATA_START_NUM;

			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;

			value_u8bit_0 = *param;
			param++;

			value_u8bit_1 = *param;
			param++;

			if(CMD_state_callback)
			{
				CMD_state_callback(value_u16bit_0, value_u8bit_0, value_u8bit_1);
			}
		}
		break;
	case CMD_COIN_IN:
		{
			param += CMD_DATA_START_NUM;
			
			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;
			
			data_write_reverse(&value_u16bit_1, param, 2);
			param += 2;
			
			value_u8bit_0 = *param;
			param++;

			memcpy(buff_128bytes_0, param, 44);
			param += 44;

			memcpy(buff_44bytes_0, param, 10);
			// param += 10;

			if(CMD_coin_in_callback)
			{
				CMD_coin_in_callback(value_u16bit_0, value_u16bit_1, value_u8bit_0, buff_128bytes_0, buff_44bytes_0);
			}
		}
		break;
	case CMD_GENERAL_CONFIG_GET:
		{
			param += CMD_DATA_START_NUM;
			
			if(CMD_universal_config_get_callback)
			{
				CMD_universal_config_get_callback();
			}
		}
		break;
	case CMD_ACCOUNT:
		{
			param += CMD_DATA_START_NUM;

			if(CMD_account_callback)
			{
				CMD_account_callback();
			}
		}
		break;
	case (CMD_SEND_COIN_PHY + 0x80):
		{
			param += CMD_DATA_START_NUM;
			
			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;

			if(CMD_coin_phy_callback)
			{
				CMD_coin_phy_callback(value_u16bit_0);
			}
		}
		break;
	case CMD_GAME_OVER + 0x80:
		{
			param += CMD_DATA_START_NUM;
			
			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;
			
			data_write_reverse(&value_u16bit_1, param, 2);
			param += 2;

			if(CMD_game_over_callback)
			{
				CMD_game_over_callback(value_u16bit_0, value_u16bit_1);
			}
		}
		break;
	case CMD_FAULT + 0x80:
		{
			param += CMD_DATA_START_NUM;
			
			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;

			if(CMD_fault_callback)
			{
				CMD_fault_callback(value_u16bit_0);
			}
		}
		break;
	case CMD_REGISTER + 0x80:
		{
			param += CMD_DATA_START_NUM;

			value_u8bit_0 = *param;
			param++;

			memcpy(buff_128bytes_0, param, GAME_MAIN_DEVICE_REGISTER_GET_KEY_NUM);
			param += GAME_MAIN_DEVICE_REGISTER_GET_KEY_NUM;

			memcpy(buff_44bytes_0, param, GAME_MAIN_DEVICE_REGISTER_GET_DEVICE_NUM_NUM);
			param += GAME_MAIN_DEVICE_REGISTER_GET_DEVICE_NUM_NUM;

			if(CMD_device_register_callback)
			{
				CMD_device_register_callback(value_u8bit_0, buff_128bytes_0, buff_44bytes_0);
			}
		}
		break;
	case CMD_LUCKY:
		{
			param += CMD_DATA_START_NUM;

			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;

			value_u8bit_0 = *param;
			param++;

			memcpy(buff_128bytes_0, param, value_u8bit_0);
			param += value_u8bit_0;

			memcpy(buff_44bytes_0, param, 44);

			if(CMD_lucky_callback)
			{
				CMD_lucky_callback(value_u16bit_0, value_u8bit_0, buff_128bytes_0, buff_44bytes_0);
			}
		}
		break;
	case CMD_MENU_SET:
		{
			param += CMD_DATA_START_NUM;

			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;

			value_u8bit_0 = *param;
			param++;

			data_write_reverse(&value_u32bit_0, param, 4);
			param += 4;

			if(value_u8bit_0 == MENU_TYPE_STRING)
			{
				if(value_u32bit_0 > 128)
				{
					memcpy(buff_128bytes_0, param, value_u32bit_0);
				}
				else
				{
					memcpy(buff_128bytes_0, param, value_u32bit_0);
				}
			}

			if(CMD_menu_set_callback)
			{
				CMD_menu_set_callback(value_u16bit_0, value_u8bit_0, value_u32bit_0, buff_128bytes_0);
			}
		}
		break;
	case CMD_MENU_READ:
		{
			param += CMD_DATA_START_NUM;

			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;

			if(CMD_menu_read_callback)
			{
				CMD_menu_read_callback(value_u16bit_0);
			}
		}
		break;

	case CMD_BOX_INFO + 0x80:
		{
			param += CMD_DATA_START_NUM;

			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;

			memcpy(buff_44bytes_0, param, GAME_MAIN_BOX_NUMBER_SIZE);
			param += GAME_MAIN_BOX_NUMBER_SIZE;

			value_u8bit_0 = *param;
			param ++;

			value_u8bit_1 = *param;
			param ++;

			memcpy(buff_128bytes_0, param, 36);

			if(CMD_box_info_callback)
			{
				CMD_box_info_callback(value_u16bit_0, buff_44bytes_0, value_u8bit_0, value_u8bit_1, buff_128bytes_0);
			}
		}
		break;

	case CMD_PAY_CODE + 0x80:
		{
			param += CMD_DATA_START_NUM;

			data_write_reverse(&value_u16bit_0, param, 2);
			param += 2;

			memcpy(buff_128bytes_0, param, GAME_MAIN_PAY_CODE_SIZE);

			if(CMD_pay_code_callback)
			{
				CMD_pay_code_callback(value_u16bit_0, buff_128bytes_0);
			}
		}
		break;

	case CMD_UPDATE_CHECK + 0x80:
		{
			param += CMD_DATA_START_NUM;

			value_u8bit_0 = *param;
			param++;

			data_write_reverse(&value_u32bit_0, param, 4);
			param += 4;

			value_u8bit_1 = *param;
			param++;

			value_u8bit_2 = *param;
			param++;

			if(CMD_update_check_callback)
			{
				CMD_update_check_callback(value_u8bit_0, value_u32bit_0, value_u8bit_1, value_u8bit_2, param);
			}
		}
		break;

	case CMD_UPDATE_GET_DATA + 0x80:
		{
			param += CMD_DATA_START_NUM;
			
			data_write_reverse(&value_u32bit_0, param, 4);
			param += 4;
			
			data_write_reverse(&value_u32bit_1, param, 4);
			param += 4;

			if(CMD_update_get_data_callback)
			{
				CMD_update_get_data_callback(value_u32bit_0, value_u32bit_1, param);
			}
		}
		break;

	default:
		break;
	}

}

//
//
//
/**
 * @brief 解码数据,
 * 把获取到的数据解码出来
 */
static void uart_data_decode(void)
{
	uint16_t i = 0;
	uint8_t c1;
	uint16_t c2;
	uint8_t sum_xor = 0;
	
	uint8_t cmd_data_get[USART1_DMA_RX_LEN];
	
	uint16_t get_head_flag = 0;
	uint16_t cmd_data_cmd = 0;
	uint16_t cmd_data_len = 0;

	for(i = 0; i < uart_data_x_config.data_get_len; i++)
	{
		c1 = uart_data_x_config.data_get[i];
		if (get_head_flag < 2)
		{
			if (c1 == parms_head[0])
			{
				memset(&cmd_data_get, 0, sizeof(cmd_data_get));

				cmd_data_get[get_head_flag] = c1;
				get_head_flag = 1;
			}
			else if (c1 == parms_head[1])
			{
				if (get_head_flag == 1)
				{
					cmd_data_get[get_head_flag] = c1;
					get_head_flag = 2;
				}
			}
		}
		else
		{
			cmd_data_get[get_head_flag] = c1;

			// CMD
			if (get_head_flag < 6 && get_head_flag >= 4)
			{
				if (get_head_flag == 4)
				{
					cmd_data_cmd = c1;
					cmd_data_cmd <<= 8;
				}
				else if (get_head_flag == 5)
				{
					cmd_data_cmd += c1;
				}
			}
			// DATA_LEN
			else if (get_head_flag < 8 && get_head_flag >= 6)
			{
				if (get_head_flag == 6)
				{
					cmd_data_len = c1;
					cmd_data_len <<= 8;
				}
				else if (get_head_flag == 7)
				{
					cmd_data_len += c1;
				}
			}
			// DATA
			else
			{
				// TAIL
				// CHECK SUM
				if (get_head_flag == (cmd_data_len + CMD_DATA_START_NUM))
				{
					sum_xor = 0;
					for (c2 = 0; c2 < (cmd_data_len + CMD_DATA_START_NUM); c2++)
					{
						sum_xor += cmd_data_get[c2];
					}

					if (sum_xor != cmd_data_get[get_head_flag])
					{
						get_head_flag = 0;
					}
				}
				// CHECK XOR
				else if (get_head_flag == (cmd_data_len + CMD_DATA_START_NUM + 1))
				{
					sum_xor = main_data_xor(cmd_data_get, (cmd_data_len + CMD_DATA_START_NUM));

					// OVER!!!!
					if (sum_xor == cmd_data_get[get_head_flag])
					{
						get_head_flag = 0;
						decode_uart_use_data(cmd_data_cmd, cmd_data_get);
					}

					get_head_flag = 0;
				}
				// // REAL DATA
				// else
				// {
				// 	//
				// }
			}
			if (get_head_flag)
			{
				get_head_flag++;
			}
		}
	}
}

//
//
//
//
//
/**
 * @brief 封装---整个发送数据的头部
 * 
 * @param send_buf 整个发送数据的buff
 * @param cmd 对应的指令
 * @param report 发送 or 回复
 * @param len 真实数据的长度
 * @return uint16_t 整个发送数据的长度
 */
uint16_t CMD_send_head(uint8_t send_buf[], uint16_t cmd, uint8_t report, uint8_t len)
{
	uint8_t buf_len;

	buf_len = 0;
	send_buf[buf_len++] = parms_head[0];
	send_buf[buf_len++] = parms_head[1];
	send_buf[buf_len++] = 0;
	send_buf[buf_len++] = 1;
	send_buf[buf_len++] = ((cmd >> 8) & 0xFF);
	if(report)
	{
		send_buf[buf_len++] = ((cmd + 0x80) & 0xFF);
	}
	else
	{
		send_buf[buf_len++] = (cmd & 0xFF);
	}

	send_buf[buf_len++] = ((len >> 8) & 0xFF);
	send_buf[buf_len++] = (len & 0xFF);

	return buf_len;
}

// xor and add end
/**
 * @brief 封装---异或检验 和 整个数据尾部
 * 
 * @param send_buf 整个发送数据的buff
 * @param sum 检验和
 * @param buf_len 整个发送数据的长度
 * @return uint16_t 增加后的整个发送数据的长度
 */
uint16_t CMD_send_tail(uint8_t *send_buf, uint8_t sum, uint16_t buf_len)
{
	uint8_t xor ;
	
	xor = main_data_xor(cmd_data_send, buf_len);

	*send_buf = sum;
	send_buf++;
	buf_len++;

	*send_buf = xor;
	send_buf++;
	buf_len++;

	*send_buf = parms_end[0];
	send_buf++;
	buf_len++;

	*send_buf = parms_end[1];
	send_buf++;
	buf_len++;

	return buf_len;
}

/**
 * @brief 封装---检验和计算
 * 
 * @param buff 整个发送数据的buff
 * @param len 整个发送数据的长度
 * @return uint8_t 检验和
 */
static uint8_t CMD_send_sum(uint8_t *buff, uint16_t len)
{
	uint8_t sum = 0;
	uint16_t i;

	for (i = 0; i < len; i++)
	{
		sum += buff[i];
		sum &= 0xFF;
	}
	
	return sum;
}

/**
 * @brief 组织整个发送数据buff
 * 
 * @param buff 整个发送数据的buff
 * @param buff_len 整个发送数据的长度
 * @param data 真实的数据
 * @param data_len 真实数据的长度
 */
static void CMD_organize_send_data(uint8_t *buff, uint16_t buff_len, uint8_t *data, uint16_t data_len)
{
	uint8_t sum = 0;

	memcpy((buff + buff_len), data, data_len);
	buff_len += data_len;

	sum = CMD_send_sum(buff, buff_len);
	buff_len = CMD_send_tail((buff + buff_len), sum, buff_len);

	uart1_dma_send_data_push(buff, buff_len);
}

//
//
//
//
//
// CMD_set

//
//
//
// connect
static uint32_t CMD_connect_ver = 132;
static uint32_t CMD_connect_product_id = 0;
static uint8_t CMD_connect_device_id[16] = {0};
static uint8_t CMD_connect_p_all = 0;
static uint8_t CMD_connect_p_use = 0;
static uint16_t CMD_connect_device_type = 0;
static uint16_t CMD_connect_soft_version = 0;

/**
 * @brief 握手初始化
 * @param connect_version 协议版本
 * @param product_id 产品编号
 * @param device_id 设备唯一ID
 * @param p_all 总p位,游戏机默认1
 * @param p_use 当前p位,游戏机默认1
 * @param device_type 设备类型
 * @param soft_version 游戏软件版本
 * @param cb 回调函数
 */
void CMD_connect_init(const uint32_t connect_version, 
					const uint32_t product_id, 
					const uint8_t *device_id, 
					const uint8_t p_all, 
					const uint8_t p_use, 
					const uint16_t device_type,
					const uint16_t soft_version,
					const CMD_connet_callback_t cb)
{
	CMD_connect_ver = connect_version;
	CMD_connect_product_id = product_id;
	memcpy(CMD_connect_device_id, device_id, sizeof(CMD_connect_device_id));
	CMD_connect_p_all = p_all;
	CMD_connect_p_use = p_use;
	CMD_connect_device_type = device_type;
	CMD_connect_soft_version = soft_version;

	CMD_connet_callback = cb;
}

/**
 * @brief 回应握手信息
 * @param  
 */
void CMD_connect_send(void)
{
	uint8_t sum = 0;
	uint64_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_CONNECT, CMD_BUFF_IS_REPORT, 30);

	cmd_data_send[buf_len] = ((CMD_connect_ver >> 24) & 0xFF);
	cmd_data_send[buf_len + 1] = ((CMD_connect_ver >> 16) & 0xFF);
	cmd_data_send[buf_len + 2] = ((CMD_connect_ver >> 8) & 0xFF);
	cmd_data_send[buf_len + 3] = (CMD_connect_ver & 0xFF);
	
	cmd_data_send[buf_len + 4] = ((CMD_connect_product_id >> 24) & 0xFF);
	cmd_data_send[buf_len + 5] = ((CMD_connect_product_id >> 16) & 0xFF);
	cmd_data_send[buf_len + 6] = ((CMD_connect_product_id >> 8) & 0xFF);
	cmd_data_send[buf_len + 7] = (CMD_connect_product_id & 0xFF);

	memcpy((cmd_data_send + buf_len + 8), CMD_connect_device_id, 16);

	cmd_data_send[buf_len + 24] = CMD_connect_p_all;
	cmd_data_send[buf_len + 25] = CMD_connect_p_use;

	cmd_data_send[buf_len + 26] = (CMD_connect_device_type >> 8) & 0xFF;
	cmd_data_send[buf_len + 27] = (CMD_connect_device_type & 0xFF);

	cmd_data_send[buf_len + 28] = (CMD_connect_soft_version >> 8) & 0xFF;
	cmd_data_send[buf_len + 29] = CMD_connect_soft_version & 0xFF;

	sum = 0;
	buf_len += 30;

	sum = CMD_send_sum(cmd_data_send, buf_len);
	buf_len = CMD_send_tail(&cmd_data_send[buf_len], sum, buf_len);

	uart1_dma_send_data_push(cmd_data_send, buf_len);
}

//
//
//
/**
 * @brief 状态同步-注册回调函数
 * 
 * @param cb 状态同步-回调函数
 */
void CMD_state_callback_register(CMD_state_callback_t cb)
{
	CMD_state_callback = cb;
}

/**
 * @brief 状态同步-回应
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_status(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_STATUS, CMD_BUFF_IS_REPORT, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 线上投币-注册回调函数
 * 
 * @param cb 线上投币回调函数
 */
void CMD_coin_in_callback_register(CMD_coin_in_callback_t cb)
{
	CMD_coin_in_callback = cb;
}

/**
 * @brief 线上投币-回应
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_coin_in_rep(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_COIN_IN, CMD_BUFF_IS_REPORT, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 通用参数设置-注册回调函数
 * 
 * @param cb 通用参数设置-回调函数
 */
void CMD_universal_config_get_callback_register(CMD_universal_config_get_callback_t cb)
{
	CMD_universal_config_get_callback = cb;
}

/**
 * @brief 通用参数设置-回应
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_universal_config_get_rep(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_GENERAL_CONFIG_GET, CMD_BUFF_IS_REPORT, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 通用游戏机查账-注册回调函数
 * 
 * @param cb 通用游戏机查账-回调函数
 */
void CMD_account_callback_register(CMD_account_callback_t cb)
{
	CMD_account_callback = cb;
}

/**
 * @brief 通用游戏机查账-回应
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_account_rep(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_ACCOUNT, CMD_BUFF_IS_REPORT, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 上报实物币-注册回调函数
 * 
 * @param cb 上报实物币-回调函数
 */
void CMD_coin_phy_callback_register(CMD_coin_phy_callback_t cb)
{
	CMD_coin_phy_callback = cb;
}

/**
 * @brief 上报实物币-发送
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_coin_phy(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_SEND_COIN_PHY, CMD_BUFF_IS_SEND, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 游戏结束-注册回调函数
 * 
 * @param cb 游戏结束-回调函数
 */
void CMD_game_over_callback_register(CMD_game_over_callback_t cb)
{
	CMD_game_over_callback = cb;
}

/**
 * @brief 游戏结束-发送
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_game_over(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_GAME_OVER, CMD_BUFF_IS_SEND, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 上报故障-注册回调函数
 * 
 * @param cb 上报故障-回调函数
 */
void CMD_fault_callback_register(CMD_fault_callback_t cb)
{
	CMD_fault_callback = cb;
}

/**
 * @brief 上报故障-发送
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_fault(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_FAULT, CMD_BUFF_IS_SEND, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 游戏机设备注册-注册回调函数
 * 
 * @param cb 游戏机设备注册-回调函数
 */
void CMD_device_register_callback_register(CMD_device_register_callback_t cb)
{
	CMD_device_register_callback = cb;
}

/**
 * @brief 游戏机设备注册-发送
 * 1.建议出厂注册一次即可.
 * 2.在获取支付盒子回调参数-已联网之后可以调用，间隔11秒轮询到有回应.
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_device_register(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_REGISTER, CMD_BUFF_IS_SEND, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 游戏机-带干预云支付-注册回调函数
 * 
 * @param cb 游戏机-带干预云支付-回调函数
 */
void CMD_lucky_callback_register(CMD_lucky_callback_t cb)
{
	CMD_lucky_callback = cb;
}

/**
 * @brief 游戏机-带干预云支付-回应
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_lucky_rep(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_LUCKY, CMD_BUFF_IS_REPORT, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 设置菜单项-注册回调函数
 * 
 * @param cb 设置菜单项-回调函数
 */
void CMD_menu_set_callback_register(CMD_menu_set_callback_t cb)
{
	CMD_menu_set_callback = cb;
}

/**
 * @brief 设置菜单项-回应
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_menu_set_rep(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_MENU_SET, CMD_BUFF_IS_REPORT, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 读取菜单项-注册回调函数
 * 
 * @param cb 读取菜单项-回调函数
 */
void CMD_menu_read_callback_register(CMD_menu_read_callback_t cb)
{
	CMD_menu_read_callback = cb;
}

/**
 * @brief 读取菜单项-回应
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_menu_read_rep(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_MENU_READ, CMD_BUFF_IS_REPORT, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
/**
 * @brief 获取支付盒子信息-注册回调函数
 * 
 * @param cb 获取支付盒子信息-回调函数
 */
void CMD_box_info_callback_register(CMD_box_info_callback_t cb)
{
	CMD_box_info_callback = cb;
}

/**
 * @brief 获取支付盒子信息-发送
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_box_info(void)
{
	uint16_t buf_len;
	
	buf_len = CMD_send_head(cmd_data_send, CMD_BOX_INFO, CMD_BUFF_IS_SEND, 0);

	CMD_organize_send_data(cmd_data_send, buf_len, NULL, 0);
}

//
//
//
/**
 * @brief 获取消费码-注册回调函数
 * 
 * @param cb 获取消费码-回调函数
 */
void CMD_pay_code_callback_register(CMD_pay_code_callback_t cb)
{
	CMD_pay_code_callback = cb;
}

/**
 * @brief 获取消费码-发送
 * @param buff 发送数据buff
 * @param len 发送数据buff长度
 */
void CMD_send_pay_code(void)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_PAY_CODE, CMD_BUFF_IS_SEND, 0);

	CMD_organize_send_data(cmd_data_send, buf_len, NULL, 0);
}

//
//
//
void CMD_update_check_callback_register(CMD_update_check_callback_t cb)
{
	CMD_update_check_callback = cb;
}

void CMD_send_update_check(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_UPDATE_CHECK, CMD_BUFF_IS_SEND, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}

//
//
//
void CMD_update_get_data_callback_register(CMD_update_get_data_callback_t cb)
{
	CMD_update_get_data_callback = cb;
}

void CMD_send_update_get_data(uint8_t *buff, uint8_t len)
{
	uint16_t buf_len;

	buf_len = CMD_send_head(cmd_data_send, CMD_UPDATE_GET_DATA, CMD_BUFF_IS_SEND, len);

	CMD_organize_send_data(cmd_data_send, buf_len, buff, len);
}
